// Asynchronous programming: futures, async, await
// https://dart.dev/codelabs/async-await

// Dart asynchronous programming: Futures
// https://medium.com/dartlang/dart-asynchronous-programming-futures-96937f831137

// Futures, async, await: Threading in Flutter
// https://medium.com/flutter-community/futures-async-await-threading-in-flutter-baeeab1c1fe3

// When to use async, await, then and Future in Dart?
// https://medium.com/@jelenaaa.lecic/when-to-use-async-await-then-and-future-in-dart-5e00e64ab9b1

// Dart futures are NOT run in a separate thread (they are run in the event loop)
// https://alvinalexander.com/misc/dart-futures-not-run-separate-thread-event-loop/

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class AsyncAwaitPage extends StatefulWidget {
  final Map<String, dynamic> arguments;
  AsyncAwaitPage({Key key, this.arguments}) : super(key: key);

  @override
  _AsyncAwaitPageState createState() => _AsyncAwaitPageState();
}

class _AsyncAwaitPageState extends State<AsyncAwaitPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AsyncAwaitPage'),
      ),
      body: ListView(
        children: <Widget>[
          ListTile(
            title: Text('''
Future.delayed()'''),
            subtitle: Column(
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: <Widget>[
                    ElevatedButton(
                      child: Text('mockError: false'),
                      onPressed: () {
                        final fetchDataFuture = fetchName(mockError: false);
                        fetchDataFuture.then((v) {
                          print('data is: ' + v);
                        }).catchError((error) {
                          print(error);
                        });
                      },
                    ),
                    ElevatedButton(
                      child: Text('mockError: true'),
                      onPressed: () {
                        final fetchDataFuture = fetchName(mockError: true);
                        fetchDataFuture.then((v) {
                          print('data is: ' + v);
                        }).catchError((error) {
                          print(error);
                        });
                      },
                    )
                  ],
                ),
              ],
            ),
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('''
async and await with try-catch'''),
            subtitle: Column(
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: <Widget>[
                    ElevatedButton(
                      child: Text('mockError: false'),
                      onPressed: () {
                        fetchStatusCode(mockError: false);
                      },
                    ),
                    ElevatedButton(
                      child: Text('mockError: true'),
                      onPressed: () {
                        fetchStatusCode(mockError: true);
                      },
                    ),
                  ],
                )
              ],
            ),
          ),
          Divider(height: 1.0),
        ],
      ),
    );
  }

  // ====================================================================================================
  // Future.delayed()
  Future<String> fetchName({bool mockError = false}) async {
    return Future.delayed(Duration(seconds: 2), () {
      if (mockError) {
        throw 'Encounter error!!!';
      } else {
        return 'Coder';
      }
    }).timeout(Duration(seconds: 3)); // 指定超时时间
  }

  // ====================================================================================================
  // async and await with try-catch
  Future fetchStatusCode({bool mockError = false}) async {
    var urlString;
    if (mockError) {
      urlString = 'https://xxyyzz.xxyyzz.xxyyzz/xxyyzz/xxyyzz.json';
    } else {
      urlString = 'https://resources.ninghao.net/demo/posts.json';
    }
    try {
      final response = await http.get(urlString);
      final statusCode = response.statusCode;
      print('statusCode is: $statusCode');
      return statusCode;
    } catch (error) {
      print(error);
    } finally {
      print('finally');
    }
  }
}
